package org.example;


import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.List;

/**
 * lxk  mvn插件开发文档  https://maven.apache.org/guides/introduction/introduction-to-plugins.html
 * 参考    https://blog.csdn.net/m0_37635806/article/details/86711423
 *
 * 1  命名规范：插件命名为<yourplugin> -maven-plugin。而maven-<yourplugin>-plugin是Maven官方插件命名规范，不可使用。
 *
 *
 * 2   隐式变量
 * maven提供三个隐式变量，用来访问系统环境变量、POM信息和maven的setting
 *
 * ${basedir} 项目根目录
 * ${project.build.directory} 构建目录，缺省为target
 * ${project.build.outputDirectory} 构建过程输出目录，缺省为target/classes
 * ${project.build.finalName} 产出物名称，缺省为 ${project.artifactId}- ${project.version}
 * ${project.packaging} 打包类型，缺省为jar
 * ${project.xxx} 当前pom文件的任意节点的内容
 *
 * 3 使用
 *
 * <plugin>
 * <groupId>com.cct.plugin</groupId>
 * <artifactId>cct-maven-plugin</artifactId>
 * <version>1.0-SNAPSHOT</version>
 * <executions>
 * <execution>
 * <id>exportDataToFile</id>
 * <phase>cct</phase>
 * <goals>
 * <goal>cct-goal</goal>
 * </goals>
 * </execution>
 * </executions>
 * </plugin>
 *
 * 运行
 * mvn groupId ：artifactId ：version ：goal
 * mvn com.cct.plugin:cct-maven-plugin:1.0-SNAPSHOT:cct-goal
 * 因为插件命名遵守${prefix}-maven-plugin,所以可以这样执行
 * mvn cct:cct-goal
 * mvnDebug com.cct.plugin:cct-maven-plugin:1.0.0:cct-goal
 *
 * 4 debug 插件
 * 在使用插件的项目中 alt+F12 mvnDebug com.cct.plugin:cct-maven-plugin:1.0.0:cct-goal
 * 在使用插件的项目 dependency 中 引入 com.cct.plugin:cct-maven-plugin:1.0.0 依赖
 * mvn插件中 右键 选中 goal debug 运行
 *
 * @author liuxiongkang
 * @- goal cct-goal
 * @- phase process-sources
 */
@Mojo(name = "cct-goal", defaultPhase = LifecyclePhase.PROCESS_SOURCES)
public class MyMojo extends AbstractMojo {

    private static final String DOT = ".";

    private static final String[] INCLUDES_DEFAULT = {"properties", "xml", "java", "yml"};

    @Parameter(defaultValue = "${basedir}")
    private File baseDir;
    @Parameter(defaultValue = "${project.build.resources}", readonly = true, required = true)
    private List<Resource> resources;
    @Parameter(defaultValue = "${project.build.sourceDirectory}", required = true, readonly = true)
    private File sourceDir;
    @Parameter(defaultValue = "${project.build.testResources}", readonly = true, required = true)
    private List<Resource> testResources;
    @Parameter(defaultValue = "${project.build.testSourceDirectory}", readonly = true, required = true)
    private File testSourceDir;
    @Parameter(property = "count.include")
    private String[] includes;

    @Override
    public void execute() throws MojoExecutionException {
        getLog().info("baseDir目录" + baseDir);
        if (includes.length == 0) {
            includes = INCLUDES_DEFAULT;
        }
        try {
            countDir(sourceDir);
            countDir(testSourceDir);
            for (Resource resource : resources) {
                countDir(new File(resource.getDirectory()));
            }
            for (Resource testResource : testResources) {
                countDir(new File(testResource.getDirectory()));
            }
        } catch (IOException e) {
            throw new MojoExecutionException(e.getMessage());
        }
    }

    private void countDir(File file) throws IOException {
        for (String fileType : includes) {
            int fileSize = baseDir.getName().length();
            String dir = file.getAbsolutePath().substring(fileSize);
            getLog().info(MessageFormat.format("{0}目录:{1}文件共计:{2}", dir, fileType, countFile(file, fileType)));
            getLog().info(MessageFormat.format("{0}目录:{1}文件代码共计行数:{2}", dir, fileType, countLine(file, fileType)));
        }
    }

    private int countFile(File file, String fileType) {
        int num = 0;
        if (file.isFile() && file.getName().endsWith(DOT + fileType)) {
            return ++num;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            assert files != null;
            for (File f : files) {
                if (f.isFile() && f.getName().endsWith(DOT + fileType)) {
                    ++num;
                } else {
                    num += countFile(f, fileType);
                }
            }
        }
        return num;
    }

    public int countLine(File file, String fileType) throws IOException {
        int countline = 0;
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            assert files != null;
            for (File f : files) {
                if (f.isFile() && f.getName().endsWith(DOT + fileType)) {
                    BufferedReader br = new BufferedReader(new FileReader(f));
                    while (br.readLine() != null) {
                        ++countline;
                    }
                } else {
                    countline += countLine(f, fileType);
                }
            }
        }
        return countline;
    }
}
